import { Request, Response } from 'express';

import {
  CallHandler,
  ExecutionContext,
  HttpStatus,
  Injectable,
  NestInterceptor,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import qs, { IParseOptions } from 'qs';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { isEmpty } from 'lodash';

import { ResOp } from '~/common/model/response.model';

import { BYPASS_KEY } from '../decorators/bypass.decorator';

/**
 * 统一处理接口请求与响应结果，如果不需要则添加 @Bypass 装饰器
 */
@Injectable()
export class TransformInterceptor implements NestInterceptor {
  constructor(private readonly reflector: Reflector) {}

  intercept(
    context: ExecutionContext,
    next: CallHandler<any>
  ): Observable<any> {
    const bypass = this.reflector.get<boolean>(
      BYPASS_KEY,
      context.getHandler()
    );

    if (bypass) return next.handle();

    const http = context.switchToHttp();
    const request = http.getRequest<Request>();

    // 处理 query 参数，将数组参数转换为数组,如：?a[]=1&a[]=2 => { a: [1, 2] }
    // const queryString = request.url.split('?')[1] || '';
    // const parsedQuery = qs.parse(queryString, {
    //   arrayFormat: 'brackets', // 支持 ?a[]=1&a[]=2 格式
    // } as IParseOptions);
    // request.query = { ...request.query, ...parsedQuery }; // 合并参数

    request['herin'] = paramsFormat(request.query);

    return next.handle().pipe(
      map(data => {
        // if (typeof data == 'undefined') {
        //   // context.switchToHttp().getResponse().status(HttpStatus.NO_CONTENT);
        //   return data;
        // }
        return new ResOp(true, HttpStatus.OK, data ?? {}, '请求成功');
      })
    );
  }
}

//格式化参数
function paramsFormat(query) {
  let returnData = { skip: 0, limit: 10 };

  if (isEmpty(query)) {
    return returnData;
  }

  if (query == undefined || query == null || JSON.stringify(query) === '{}') {
    return returnData;
  }

  const pageFormate = formatPageAndPageSize(query.page, query.pageSize);

  returnData = {
    skip: pageFormate.skip,
    limit: pageFormate.limit,
  };

  return returnData;
}

function formatPageAndPageSize(
  page?: string | number,
  pageSize?: string | number
): { skip: number; limit: number } {
  const PAGE_DEFAULT = 1;
  const PAGESIZE_DEFAULT = 10;
  // 判断不存在
  if (!page || page == 0) page = PAGE_DEFAULT;
  if (!pageSize) pageSize = PAGESIZE_DEFAULT;
  // 转换数字
  if (typeof page === 'string') page = parseInt(page);
  if (typeof pageSize === 'string') pageSize = parseInt(pageSize);
  // 转换失败
  if (isNaN(page)) page = PAGE_DEFAULT;
  if (isNaN(pageSize)) pageSize = PAGESIZE_DEFAULT;

  const skip = (page - 1) * pageSize;

  const limit = pageSize;

  return { skip, limit };
}
